interface Filter {
    execute(request: string): void;
}

class AuthenticationFilter implements Filter {
    public execute(request: string): void {
        console.log("Authenticating request: " + request);
    }
}

class DebugFilter implements Filter {
    public execute(request: string): void {
        console.log("Request log: " + request);
    }
}

class Target {
    public execute(request: string): void {
        console.log("Executing request: " + request);
    }
}

class FilterChain {
    private filters: Filter[] = [];
    private target: Target | null = null;
    public addFilter(filter: Filter): void {
        this.filters.push(filter);
    }
    public execute(request: string): void {
        this.filters.forEach(filter => filter.execute(request));
        this.target?.execute(request);
    }
    public setTarget(target: Target): void {
        this.target = target;
    }
}

class FilterManger {
    filterChain: FilterChain;
    public constructor(target: Target) {
        this.filterChain = new FilterChain();
        this.filterChain.setTarget(target);
    }
    public setFilter(filter: Filter): void {
        this.filterChain.addFilter(filter);
    }
    public filterRequest(request: string): void {
        this.filterChain.execute(request);
    }
}

class Client {
    filterManager: FilterManger | null = null;
    public setFilterManager(filterManager: FilterManger): void {
        this.filterManager = filterManager;
    }
    public sendRequest(request: string): void {
        this.filterManager?.filterRequest(request);
    }
}

function main() {
    const manager: FilterManger = new FilterManger(new Target());
    manager.setFilter(new AuthenticationFilter());
    manager.setFilter(new DebugFilter());
    const client: Client = new Client();
    client.setFilterManager(manager);
    client.sendRequest("Hello World");
}

main();
